From f096c11828df983c5581bb96e8b238543652c008 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Tue, 14 Mar 2023 16:49:46 +0000
Subject: [PATCH] staging: bcm2835-codec: Add support for
 V4L2_CID_MPEG_VIDEO_GOP_SIZE

For H264, V4L2_CID_MPEG_VIDEO_H264_I_PERIOD is meant to be the intra
I-frame period, whilst V4L2_CID_MPEG_VIDEO_GOP_SIZE is the intra IDR
frame period.
The firmware encoder doesn't produce I-frames that aren't IDR as well,
therefore V4L2_CID_MPEG_VIDEO_GOP_SIZE is technically the correct
control, however users may have adopted V4L2_CID_MPEG_VIDEO_H264_I_PERIOD.

Add support for V4L2_CID_MPEG_VIDEO_GOP_SIZE controlling the encoder,
and have VIDIOC_S_CTRL for V4L2_CID_MPEG_VIDEO_H264_I_PERIOD update
the value for V4L2_CID_MPEG_VIDEO_GOP_SIZE (the reverse is not
implemented).

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
 .../bcm2835-codec/bcm2835-v4l2-codec.c          | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
@@ -705,6 +705,7 @@ struct bcm2835_codec_ctx {
 	struct bcm2835_codec_dev	*dev;
 
 	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *gop_size;
 
 	struct vchiq_mmal_component  *component;
 	bool component_enabled;
@@ -2286,6 +2287,17 @@ static int bcm2835_codec_s_ctrl(struct v
 		break;
 
 	case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
+		/*
+		 * Incorrect initial implementation meant that H264_I_PERIOD
+		 * was implemented to control intra-I period. As the MMAL
+		 * encoder never produces I-frames that aren't IDR frames, it
+		 * should actually have been GOP_SIZE.
+		 * Support both controls, but writing to H264_I_PERIOD will
+		 * update GOP_SIZE.
+		 */
+		__v4l2_ctrl_s_ctrl(ctx->gop_size, ctrl->val);
+	fallthrough;
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
 		if (!ctx->component)
 			break;
 
@@ -3360,7 +3372,7 @@ static int bcm2835_codec_open(struct fil
 	case ENCODE:
 	{
 		/* Encode controls */
-		v4l2_ctrl_handler_init(hdl, 12);
+		v4l2_ctrl_handler_init(hdl, 13);
 
 		v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
 				       V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
@@ -3425,6 +3437,9 @@ static int bcm2835_codec_open(struct fil
 				  V4L2_CID_MPEG_VIDEO_B_FRAMES,
 				  0, 0,
 				  1, 0);
+		ctx->gop_size = v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
+						  V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+						  0, 0x7FFFFFFF, 1, 60);
 		if (hdl->error) {
 			rc = hdl->error;
 			goto free_ctrl_handler;
